/**
\page page_extension_system Extension System

<table CELLPADDING=0 style="width:100%;
  table-layout:fixed;
	margin:0px 0px 0px 0px;
	border-width:0px 0px 0px 0px; 
	border-color:#7F7F7F;">
<tr> 

<td style="width:80%; padding:0px 5px 0px 0px; vertical-align: text-top; text-align: left">
<h1 style="margin:0px; padding:0px">Overview</h1>

%Qtilities provides an extension management library which has the following goals and responsibilities:
- Define how plugins interface with an application.
- Getting the plugins up and running. This includes plugin loading, initialization and finalization.
- Provide management of plugin configuration sets, that is: Provide control over which plugins must be loaded and initialized.
- Provide information about the loaded plugins once they are loaded and initialized.

The Qtilities::ExtensionSystem::ExtensionSystemCore singleton provides the interface through which these tasks can be achieved.  This article will provide details of how the extension system achieves these goals and give an overview of the different features provided.

Table of contents:
- \ref define_plugins
- \ref define_lifetime_management
    - \ref loading_plugins
    - \ref init_and_finalization_sequence
    .
- \ref plugin_information
- \ref plugin_config_sets
    - \ref plugin_different_types
    - \ref plugin_creating_sets
    - \ref plugin_creating_sets_user
    .

</td>

<td style="width:20%; vertical-align: top; margin:0px 0px 0px 0px;">
<table style="table-layout:auto;
	margin:0px 0px 0px 0px; 
  width: 100%;
	border-width:0px 0px 0px 0px; 
	border-color:#7F7F7F;
  background-color: #d1d3d4;">
<tr>
<td style="background-color: #5a5c5e; text-align: center">
<h2 style ="color:#FFFFFF">First Steps</h2>
</td>
</tr>
<tr>
<td>
- <a href="page_getting_started.html">Getting Started</a><br>
- <a href="page_the_basics.html">The Basics</a><br>
- <a href="page_examples_and_plugins.html">Examples and Plugins</a><br>
</td>
</tr>
<tr>
<td style="background-color: #5a5c5e; text-align: center">
<h2 style ="color:#FFFFFF">Overviews</h2>
</td>
</tr>
<tr>
<td>
- <a href="page_action_management.html">Action Management</a><br>
- <a href="page_tree_structures.html">Building Trees</a><br>
- <a href="page_debugging.html">Debugging Applications</a><br>
- <a href="page_extension_system.html">Extension System</a><br>
- <a href="page_factories.html">Factories</a><br>
- <a href="page_logging.html">Logging</a><br>
- <a href="page_modules_overview.html">Modules</a><br>
- <a href="page_object_management.html">Object Management</a><br>
- <a href="page_observers.html">Observers</a><br>
- <a href="page_observer_widgets.html">Observer Widgets</a><br>
- <a href="page_project_management.html">Project Management</a><br>
- <a href="page_tasking.html">Tasking</a><br>
- <a href="page_widget_set.html">Widget Set</a><br>
</td>
</tr>
</table>
</td>
</tr>
</table>

\section define_plugins Goal 1: Define how plugins interface with an application

The Qtilities::ExtensionSystem::Interfaces::IPlugin interface defines the interface between the extension system and plugins it can load. The interface provides status information about the state of a plugin as well as information about the plugin itself and was made as lightweight as possible. Therefore it does not inherit from anything and any object can implement it.

Lets look at a simplified version of the \p PluginTemplate example in the \p QtilitiesPlugins project which is a ready to use template implementing this interface. First lets look at the header %file:
\code
class PluginTemplate : public QObject, public IPlugin
{
    Q_OBJECT
    Q_INTERFACES(Qtilities::ExtensionSystem::Interfaces::IPlugin)

public:
    PluginTemplate(QObject* parent = 0);
    ~PluginTemplate() {}

    // --------------------------------
    // IObjectBase Implementation
    // --------------------------------
    QObject* objectBase() { return this; }
    const QObject* objectBase() const { return this; }

    // --------------------------------------------
    // IPlugin Implementation
    // --------------------------------------------
    bool initialize(const QStringList &arguments, QStringList *error_strings);
    bool initializeDependencies(QStringList *error_strings);
    void finalize() {}
    QString pluginName() const { return "Example Plugin"; }
    QtilitiesCategory pluginCategory() const { return QtilitiesCategory("General"); }
    VersionInformation pluginVersionInformation() const;
    QString pluginPublisher() const;
    QString pluginPublisherWebsite() const;
    QString pluginPublisherContact() const;
    QString pluginDescription() const;
    QString pluginCopyright() const;
    QString pluginLicense() const;
};
\endcode

Next we look at the \p .cpp implementation %file:
\code
PluginTemplate::PluginTemplate(QObject* parent) : QObject(parent) {
    setObjectName(pluginName());
}

bool PluginTemplate::initialize(const QStringList &arguments, QStringList *error_strings) {
    Q_UNUSED(arguments)
    Q_UNUSED(error_strings)

    return true;
}

bool PluginTemplate::initializeDependencies(QStringList *error_strings) {
    Q_UNUSED(error_strings)

    return true;
}

Qtilities::Core::VersionInformation PluginTemplate::pluginVersionInformation() const {
    VersionInformation version_info(1,0,0);
    return version_info;
}

QString PluginTemplate::pluginPublisher() const {
    return "Jaco Naudé";
}

QString PluginTemplate::pluginPublisherWebsite() const {
    return "http://www.qtilities.org";
}

QString PluginTemplate::pluginPublisherContact() const {
    return "support@qtilities.org";
}

QString PluginTemplate::pluginDescription() const {
    return tr("An example Qtilities Extension System plugin.");
}

QString PluginTemplate::pluginCopyright() const {
    return QString(tr("Copyright") + " 2010, Jaco Naudé");
}

QString PluginTemplate::pluginLicense() const {
    return tr("See the Qtilities Libraries license");
}

Q_EXPORT_PLUGIN2(PluginTemplate, PluginTemplate);
\endcode

The implementation above shows that it is very easy to implement the interface and the best place to start is to use Qtilities::Plugins::Template.

\section define_lifetime_management Goal 2: Getting the plugins up and running

\subsection loading_plugins Loading plugins

The Qtilities::ExtensionSystem::ExtensionSystemCore::initialize() function loads plugins from path(s) defined in Qtilities::ExtensionSystem::ExtensionSystemCore::pluginPaths(). By default all plugins in the \p EXECUTABLE_PATH/plugin directory are loaded and new paths can be added using the Qtilities::ExtensionSystem::ExtensionSystemCore::addPluginPath() function.

During the loading process, the extension system core class emits the \p newProcessMessage() signal with progress messages which can be connected to a splash window if necessary (see the Qtilities::Examples::MainWindow example which demonstrates this for more information). 

The example below shows how to use the extension system to load plugins in your application's main() function.

\code
#include <QtGui>
#include <QtilitiesExtensionSystem>
using namespace QtilitiesCore;
using namespace QtilitiesCoreGui;
using namespace QtilitiesExtensionSystem;

int main(int argc, char *argv[])
{
  QtilitiesApplication a(argc, argv);

  // We must specify the following if we want the logger to remember its settings:
  QtilitiesApplication::setOrganizationName("Jaco Naudé");
  QtilitiesApplication::setOrganizationDomain("Qtilities");
  QtilitiesApplication::setApplicationName("Extension System Example");
  QtilitiesApplication::setApplicationVersion("0.1");	 

  // Initialize the logger:
  QtilitiesApplication::applicationSessionPath();
  LOG_INITIALIZE();

  // Set the Qt message engine active, this will log messages to the Qt debugging system during the plugin loading process:
  Log->toggleQtMsgEngine(true);
  // Load plugins using the extension system:
  EXTENSION_SYSTEM->initialize();
  // Set the Qt message engine inactive once the process loading process is completed:
  Log->toggleQtMsgEngine(false);

  // Register extension system config page:
  OBJECT_MANAGER->registerObject(EXTENSION_SYSTEM->configWidget());

  // Report on the number of config pages found:
  QList<QObject*> registered_config_pages = OBJECT_MANAGER->registeredInterfaces("com.Qtilities.CoreGui.IConfigPage/1.0");
  LOG_INFO(QString("%1 configuration page(s) found in set of loaded plugins.").arg(registered_config_pages.count()));

  // Create a config widget for this example:
  ConfigurationWidget config_widget;
  config_widget.initialize(registered_config_pages);
  
  exampleMainWindow->show();
  int result = a.exec();
  
  // Finalize all plugins:
  EXTENSION_SYSTEM->finalize();
  // Finalize the logger:
  LOG_FINALIZE();
  
  return result;
}

\endcode

The above example registers the Qtilities::ExtensionSystem::PluginInfoWidget widget in the global object pool which is discussed in the \ref plugin_information section.

\subsection init_and_finalization_sequence Plugin initialization and finalization

The diagram below shows the sequence in which plugins are initialized during the plugin loading process.

\image html plugin_loading_sequence.jpg "Plugin Loading Sequence"

Plugins should register any objects in which other plugins or the main application might be interested in (configuration pages, contexts) etc. in the Qtilities::ExtensionSystem::Interfaces::IPlugin::initialize() function implementation. After all plugin instances were created and added to the global object pool, this function is called on all plugins. That is, all plugins are loaded first before any of them are initialized. To make things clear, lets look at simplified version of the \p initialize() function implementation in the Qtilities::Plugins::SessionLog plugin:

\code
bool Qtilities::Plugins::SessionLog::SessionLogPlugin::initialize(const QStringList &arguments, QStringList *error_strings) {
    Q_UNUSED(arguments)
    Q_UNUSED(error_strings)

    // Add the session log mode to the global object pool:
    SessionLogMode* session_log_mode = new SessionLogMode();
    OBJECT_MANAGER->registerObject(session_log_mode);

    // Register the context of the session log mode:
    CONTEXT_MANAGER->registerContext(session_log_mode->contextString());

    // Register the logging configuration widget:
    OBJECT_MANAGER->registerObject(LoggerGui::createLoggerConfigWidget(false));

    return true;
}
\endcode

This is followed by calling the Qtilities::ExtensionSystem::Interfaces::IPlugin::initializeDependencies() function on all plugins. In this function plugins can inspect the global object pool to for interfaces they are interested in using the Qtilities::Core::Interfaces::IObjectManager::registeredInterfaces() function. Again, to make things clear lets write an implementation of the \p initializeDependencies() function which looks for all projects parts registered in the global object pool:

\code
bool ProjectPartFinderPlugin::initializeDependencies(QStringList *error_strings) {
    Q_UNUSED(error_strings)

    // Get a list of all the project items in the object pool:
    QList<QObject*> projectItemObjects = OBJECT_MANAGER->registeredInterfaces("com.Qtilities.ProjectManagement.IProjectItem/1.0");
    QList<IProjectItem*> projectItems;

    // Cast all items:
    for (int i = 0; i < projectItemObjects.count(); i++) {
        IProjectItem* part = qobject_cast<IProjectItem*> (projectItemObjects.at(i));
        if (part)
          projectItems.append(part);
    }
    
    // Now we will have a list with all the project items in the global object pool.
    return true;
}
\endcode

\section plugin_information Goal 3: Provide plugin information at runtime

The main access point to information about loaded plugins is the extension system configuration widget class (Qtilities::ExtensionSystem::ExtensionSystemConfig). The configuration widget is shown below:

\image html extension_system_configuration_widget.jpg "Extension System Widget Plugin Overview"

The "Plugin Paths" tab in the configuration widget provides details about the paths searched for plugins, thus it shows the paths returned by Qtilities::ExtensionSystem::ExtensionSystemCore::pluginPaths(). For each plugin we can get detailed information by double clicking its name, or by clicking the "Details" button. The image below shows the detailed information of one of the provided %Qtilities plugins.

\image html extension_system_details_widget.jpg "Plugin Details"

\section plugin_config_sets Goal 4: Provide management of plugin configuration sets

In advanced applications it is often desirable to specify a set of plugins which should be loaded for different scenarios. In %Qtilities we call a set of plugins that must be loaded for a specific scenario a plugin configuration set.

\subsection plugin_different_types Plugin Classification

The extension system allow management of different configuration sets which groups plugins into the following groups:
- <b>Active Plugins:</b> Plugins which are loaded and initialized.
- <b>Inactive Plugins:</b> Plugins which are loaded but not initialized. This is needed in order for the plugin to still be shown in the plugin details widget and to allow user control over creation of configuration sets.
- <b>Filtered Plugins:</b> Plugins which are filtered/skipped, thus not loaded or initialized. This is usefull in scenarios where the same application is deployed to different places and only specific plugins should be exposed to users when they create plugin configuration sets.
- <b>Core Plugins:</b> These plugins form the core of an application. Thus they must always be treated as active plugins (thus loaded and initialized).

A configuration set gives the names of the plugins which falls into the inactive and filtered plugin groups. When a plugin is found during the Qtilities::ExtensionSystem::ExtensionSystemCore::initialize() function call, the plugin is checked agains the information provided by the configuration set and handled accordingly. When a plugin is found which is not categorized in the configuration set, it automatically falls under the Active Plugins category. In the same way, if a plugin occurs under more than one category in the configuration set, it automatically falls under the Active Plugins set.

The Qtilities::ExtensionSystem::ExtensionSystemCore class provides different functions to get information about the plugins that fell into the different categories during initialization.

\subsection plugin_creating_sets Creating Configuration Sets

Creating configuration sets is easy and flexible. The important thing to remember is: The plugin configuration set that will be used is the one that is active at the time that the extension system's \p initialize() function is called. There are different ways to set it up:
- Manually calling the functions that grounp plugins into different categories, like Qtilities::ExtensionSystem::ExtensionSystemCore::setCorePlugins() for example.
- Loading the configuration from a XML file (ending with \p .pconfig by default). The configuration setup can be saved to a XML file at any stage. The debug plugin allows you to create custom sets, for more information see \ref debugging_plugins_custom.

Below is an example plugin configuration set %file:

\code
<!DOCTYPE QtilitiesPluginConfiguration>
<QtilitiesPluginConfiguration QtilitiesVersion="0.3.0" ExportVersion="0">
  <InactivePlugins>
    <PluginName Value="Test Plugin 1"/>
    <PluginName Value="Test Plugin 2"/>
    <PluginName Value="Test Plugin 3"/>
  </InactivePlugins>
  <FilteredPlugins>
    <Expression Value="Filter1*"/>
    <Expression Value="Filter2*"/>
    <Expression Value="Filter3*"/>
  </FilteredPlugins>
</QtilitiesPluginConfiguration>
\endcode

\subsection plugin_creating_sets_user Allowing Users Control Over Sets

The developer will have a specific way in mind that he or she wants to manage configuration sets their of application. To accomodate different scenarios the way that sets are handled can be customized through the \p ExtensionSystemCore class. It is for example possible to define some core plugins and then let the user decide which plugins they want to be active and incative.

The plugin details widget can either show the current active and inactive plugins without allowing the user to change it, or it can give full control to the user.
To show the activity of plugins and to allow the users to control the activity of plugins, use the following functions on the extension system:

\code
EXTENSION_SYSTEM->enablePluginActivityDisplay();
EXTENSION_SYSTEM->enablePluginActivityControl();
\endcode

Below is an example of the plugin configuration widget with the above two activity options enabled and with the "Session Log Plugin" specified to be a core plugin (thus it is greyed out to indicate this and a proper message is displayed when an attempt is made to deactivate it). The image shows the state of the widget just after the user disabled the "Project Management Plugin".

\image html extension_system_widget_with_config_control.jpg "Plugin Configuration Set Display"

When the user is given control over plugin configuration sets, changing the current set will automatically save the new configuration to the file name of the loaded set. By default this is \p App_Path/session/default.pconfig. However if a valid plugin configuration has been loaded using the Qtilities::ExtensionSystem::ExtensionSystemCore::loadPluginConfiguration() function, this loaded configuration file will be updated to reflect the changes the user made. The Qtilities::ExtensionSystem::ExtensionSystemCore::setActivePluginConfigurationFile() function can be specified. It is important to note that the extension system's \p initialize() function loads the active plugin configuration file automatically if it exists. Thus is does not make sense to load the configuration before calling \p initialize() unless you want to modify it.
 
*/
